package clock.socoolby.com.clock.widget.animatorview.animator;

import android.graphics.Canvas;
import android.graphics.Paint;
import clock.socoolby.com.clock.widget.animatorview.AbstractAnimator;
import clock.socoolby.com.clock.widget.animatorview.I_AnimatorEntry;


//引用自：https://blog.csdn.net/longyc2010/article/details/44137225

public class BubbleWhirlPoolAnimator extends AbstractAnimator<BubbleWhirlPoolAnimator.Circle> {
    private static final String TAG = "BubbleWhirlPoolAnimator";
    private static final int NORTH = 0;
    private static final int SOUTH = 1;
    private static final int EAST = 2;
    private static final int WEST = 3;
    private static final int NORTH_WEST = 4;
    private static final int NORTH_EAST = 5;
    private static final int SOUTH_WEST = 6;
    private static final int SOUTH_EAST = 7;

    public static final String NAME="BubbleWhirl";

    //private Paint paint = new Paint();
    private boolean isChangeRunning = false;
    private int frequency = 0;

    public BubbleWhirlPoolAnimator(int entryQuantity) {
        super(entryQuantity);
    }

    public BubbleWhirlPoolAnimator() {
        super(10);
    }

    @Override
    public boolean run() {
        if (frequency % 5 == 0) {
            for (Circle c : list) {
                isChangeRunning=rand.nextInt(5)!=1;
                if (isChangeRunning) {
                    c.runBubble();
                } else {
                    c.increase();
                }
            }
        }
        frequency++;
        return true;
    }


    @Override
    public void onDraw(Canvas canvas) {
        for (Circle c : list) {
            c.onDraw(canvas, mPaint);
        }
    }

    @Override
    public Circle createNewEntry() {
        randomColorIfAble();
        return new Circle(rand.nextInt(width), rand.nextInt(height), rand.nextInt(30) + 20, rand.nextInt(60) + 40,color);
    }


    private class CircleCenterPoint {
        private float x;
        private float y;

        public CircleCenterPoint(float x, float y) {
            this.x = x;
            this.y = y;
        }

        public float getX() {
            return x;
        }

        public void setX(float x) {
            this.x = x;
        }

        public float getY() {
            return y;
        }

        public void setY(float y) {
            this.y = y;
        }

        public boolean isOutOfView(float r) {
            boolean isOutView = false;
            if (x > width - r || x < r || y > height - r || y <= r) {
                isOutView = true;
            }

            return isOutView;
        }

        public boolean isInCenterView(float r, float centerViewR) {
            boolean isOutView = false;
            if (x > width / 2 - centerViewR && x < width / 2 + centerViewR
                    && y > height / 2 - centerViewR && y <= height / 2 + centerViewR) {
                isOutView = true;
            }
            return isOutView;
        }
    }

    public class Circle implements I_AnimatorEntry {
        private CircleCenterPoint center;
        private float r;
        private int a;
        private int aMax;
        private double distance;
        private double minDistance;
        private int type = rand.nextInt(100);
        private int count = 0;

        private double delta = 0.1f;
        private double theta = 0;

        private boolean isInitDistance = false;
        private double delta2 = 0.1f;
        boolean isShouldDisapear = false;
        int circleColor=0;

        public Circle(float x, float y, float r, int a,int color) {
            center = new CircleCenterPoint(x, y);
            this.r = r;
            this.a = a;
            minDistance = rand.nextInt(100);
            this.circleColor=color;
        }

        public void runBubble() {
            if (!isInitDistance) {
                isInitDistance = true;
                float x = center.getX() - width / 2;
                float y = center.getY() - height / 2;

                distance = Math.sqrt((double) (x * x + y * y));

                if (x > 0) {

                    theta = Math.atan(y / x);
                } else {

                    theta = Math.atan(y / x) + Math.PI;
                }

            }
            theta = theta + 0.1;
            distance = getDistance(distance);
            center.setY((float) (distance * Math.sin(theta)) + height / 2);
            center.setX((float) (distance * Math.cos(theta)) + width / 2);
        }

        public void increase() {
            if (isInitDistance) {
                delta = 0.1f;
                isInitDistance = false;
            }
            changeCenterPoint(center, type);

            if (center.isOutOfView(r) || center.isInCenterView(r, 100f)) {
                isShouldDisapear = true;

            }
        }


        private double getDistance(double distance) {

            double result = distance;
            delta = delta + 0.1;

            result = result - delta * delta;
            if (result < minDistance) {
                result = minDistance;
            }
            return result;
        }

        @Override
        public void move(int maxWidth, int maxHight) {

        }

        @Override
        public void onDraw(Canvas canvas, Paint mPaint) {
            count++;
            if (count % ((type + 8) * 10) == 0) {
                type = rand.nextInt(100);
            }
            if (isShouldDisapear) {
                a--;
                if (a <= 0) {
                    isShouldDisapear = false;
                    center.setX(rand.nextInt(width));
                    center.setY(rand.nextInt(height));
                    r = rand.nextInt(30) + 20;
                    aMax = rand.nextInt(60) + 40;
                }

            } else {

                if (a <= aMax) {
                    a++;
                } else {
                    aMax = 0;
                }
            }
            mPaint.reset();
            mPaint.setColor(circleColor);
            mPaint.setAlpha(a);
            canvas.drawCircle(center.getX(), center.getY(), r, mPaint);
        }

        @Override
        public void setAnimatorEntryColor(int color) {
            this.circleColor=color;

        }
    }

    private void changeCenterPoint(CircleCenterPoint center, int type) {

        switch (type % 8) {
            case NORTH:
                center.setX(center.getX());
                center.setY(center.getY() - rand.nextInt(4));
                break;
            case SOUTH:
                center.setX(center.getX());
                center.setY(center.getY() + rand.nextInt(4));
                break;
            case EAST:
                center.setX(center.getX() + rand.nextInt(4));
                center.setY(center.getY());
                break;
            case WEST:
                center.setX(center.getX() - rand.nextInt(4));
                center.setY(center.getY());

                break;
            case NORTH_WEST:
                center.setX(center.getX() - rand.nextInt(4));
                center.setY(center.getY() - rand.nextInt(4));
                break;
            case NORTH_EAST:
                center.setX(center.getX() + rand.nextInt(4));
                center.setY(center.getY() - rand.nextInt(4));
                break;
            case SOUTH_WEST:
                center.setX(center.getX() + rand.nextInt(4));
                center.setY(center.getY() + rand.nextInt(4));
                break;
            case SOUTH_EAST:
                center.setX(center.getX() - rand.nextInt(4));
                center.setY(center.getY() + rand.nextInt(4));
                break;
        }
    }
}


